package com.codedancer.campus.manager.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.manager.service.IMenuService;
import com.codedancer.campus.manager.service.bo.menu.MenuAddOrUpdateBo;
import com.codedancer.campus.manager.service.vo.menu.MenuVO;
import com.codedancer.campus.mapper.MenuMapper;
import com.codedancer.campus.mapper.RoleMenuMapper;
import com.codedancer.campus.po.Menu;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
public class MenuServiceImpl implements IMenuService {

    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;

    /**
     * 添加菜单
     *
     * @param menuAddOrUpdateBo
     */
    @Override
    public void add(MenuAddOrUpdateBo menuAddOrUpdateBo) {
        if (menuAddOrUpdateBo.getIsRouter() && ObjectUtil.isEmpty(
            menuAddOrUpdateBo.getComponentName())) {
            throw new BusinessException("请填写组件名称");
        }
        if (menuAddOrUpdateBo.getIsRouter() && ObjectUtil.isEmpty(
            menuAddOrUpdateBo.getPath())) {
            throw new BusinessException("请填写路径");
        }
        Menu menu = BeanUtil.copyProperties(menuAddOrUpdateBo, Menu.class);
        menu.setUuid(UUIDGenerator.getUUID());
        // 获取父级菜单最大的排序
        Integer maxSort = menuMapper.selectMaxSortByParentUuid("0");
        menu.setSort(maxSort + 1);
        menuMapper.insert(menu);
    }

    /**
     * 根据父级uuid获取下级菜单
     *
     * @param parentUuid
     * @return
     */
    @Override
    public List<MenuVO> listByParentUuid(String parentUuid) {
        List<Menu> childrenMenus = menuMapper.listByParentUuidOrderBySortAsc(parentUuid);
        List<MenuVO> menuVOS = new ArrayList<>();
        for (Menu childrenMenu : childrenMenus) {
            MenuVO menuVO = BeanUtil.copyProperties(childrenMenu, MenuVO.class);
            if (menuMapper.existsByColumn("parent_uuid", childrenMenu.getUuid())) {
                menuVO.setHasChildren(true);
            }
            Menu parentMenu = menuMapper.selectById(childrenMenu.getParentUuid());
            menuVO.setParentMenuName(ObjectUtil.isNotEmpty(parentMenu) ? parentMenu.getName() : "");
            menuVOS.add(menuVO);
        }
        return menuVOS;
    }

    /**
     * 添加子集菜单
     *
     * @param menuAddOrUpdateBo
     * @return
     */
    @Override
    public MenuVO addChildren(MenuAddOrUpdateBo menuAddOrUpdateBo) {
        if (menuAddOrUpdateBo.getIsRouter() && ObjectUtil.isEmpty(
            menuAddOrUpdateBo.getComponentName())) {
            throw new BusinessException("请填写组件名称");
        }
        if (menuAddOrUpdateBo.getIsRouter() && ObjectUtil.isEmpty(
            menuAddOrUpdateBo.getPath())) {
            throw new BusinessException("请填写路径");
        }
        if (!menuMapper.existsByUuId(menuAddOrUpdateBo.getParentUuid())) {
            throw new BusinessException("父级菜单不存在");
        }
        Menu menu = BeanUtil.copyProperties(menuAddOrUpdateBo, Menu.class);
        menu.setUuid(UUIDGenerator.getUUID());
        // 获取父级菜单最大的排序
        Integer maxSort = menuMapper.selectMaxSortByParentUuid(menuAddOrUpdateBo.getParentUuid());
        menu.setSort(maxSort + 1);
        menuMapper.insert(menu);
        return BeanUtil.copyProperties(menu, MenuVO.class);
    }

    /**
     * 删除菜单
     *
     * @param uuid
     */
    @Override
    public void delete(String uuid) {
        if (!menuMapper.existsByUuId(uuid)) {
            throw new BusinessException("删除的菜单不存在");
        }
        // 先删除子集菜单
        menuMapper.deleteByColumn("parent_uuid", uuid);
        // 删除角色关联的菜单
        roleMenuMapper.deleteByColumn("menu_uuid", uuid);
        // 再删除父级菜单
        menuMapper.deleteById(uuid);
    }

    /**
     * 修改菜单
     *
     * @param menuAddOrUpdateBo
     */
    @Override
    public void update(MenuAddOrUpdateBo menuAddOrUpdateBo) {
        if (menuAddOrUpdateBo.getIsRouter() && ObjectUtil.isEmpty(
            menuAddOrUpdateBo.getComponentName())) {
            throw new BusinessException("请填写组件名称");
        }
        Menu menu = menuMapper.findById(menuAddOrUpdateBo.getUuid())
            .orElseThrow(() -> new BusinessException("菜单不存在"));
        BeanUtil.copyProperties(menuAddOrUpdateBo, menu);
        menuMapper.updateById(menu);
    }

    /**
     * 上移
     *
     * @param uuid
     */
    @Override
    public void moveUp(String uuid) {
        Menu menu = menuMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("菜单不存在"));
        if (menu.getSort() == 1) {
            throw new BusinessException("已经是第一个，不能进行上移");
        }
        // 获取上一个菜单
        Menu prevMenu = menuMapper.selectMenuByParentUuidAndSort(menu.getParentUuid(),
            menu.getSort() - 1);
        Integer tempSort = prevMenu.getSort();
        prevMenu.setSort(menu.getSort());
        menu.setSort(tempSort);
        menuMapper.updateById(menu);
        menuMapper.updateById(prevMenu);
    }

    /**
     * 下移
     *
     * @param uuid
     */
    @Override
    public void moveDown(String uuid) {
        Menu menu = menuMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("菜单不存在"));
        // 获取父级菜单最大的排序
        Integer maxSort = menuMapper.selectMaxSortByParentUuid(menu.getParentUuid());
        if (Objects.equals(menu.getSort(), maxSort)) {
            throw new BusinessException("已经是最后一个，不能进行下移");
        }
        // 获取下一个菜单
        Menu nextMenu = menuMapper.selectMenuByParentUuidAndSort(menu.getParentUuid(),
            menu.getSort() + 1);
        Integer tempSort = nextMenu.getSort();
        nextMenu.setSort(menu.getSort());
        menu.setSort(tempSort);
        menuMapper.updateById(menu);
        menuMapper.updateById(nextMenu);
    }
}
